package com.acme.service.bank;

import com.acme.domain.account.Account;
import com.acme.domain.account.CheckingAccount;
import com.acme.domain.account.SavingAccount;
import com.acme.domain.bank.Bank;
import com.acme.domain.bank.Client;
import com.acme.domain.bank.Gender;
import com.acme.exceptions.BrokenBankFeedFileException;
import com.acme.exceptions.ClientExistsException;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BankDataLoader {
    /**
     * Loads a file which contains data feed in the following format: <br>
     * accounttype=c|s;balance=100;overdraft=50;name=John;gender=m|f;
     *
     * @param bank All loaded data will be saved in this Bank object.
     * @param path Path to bank feed file.
     * @throws FileNotFoundException if file for specified path is not found
     * @throws com.acme.exceptions.BrokenBankFeedFileException
     *                               if bank feed file contains broken data
     */
    public void load(final Bank bank, final String path) throws FileNotFoundException, BrokenBankFeedFileException {
        Scanner scanner = new Scanner(new FileInputStream(path));
        while (scanner.hasNext()) {
            String clientDataLine = scanner.next();
            Pattern keyValuePattern = Pattern.compile("(\\w*)=(.*?);");
            Matcher matcher = keyValuePattern.matcher(clientDataLine);

            String accountTypeString = null;
            double balance = 0;
            double overdraft = 0;
            String name = null;
            Gender gender = null;
            while (matcher.find()) {
                String key = matcher.group(1);
                String value = matcher.group(2);
                switch (key) {
                    case "accounttype":
                        accountTypeString = value;
                        break;
                    case "balance":
                        balance = Double.parseDouble(value);
                        break;
                    case "overdraft":
                        overdraft = Double.parseDouble(value);
                        break;
                    case "name":
                        name = value;
                        break;
                    case "gender":
                        switch (value) {
                            case "m":
                                gender = Gender.MALE;
                                break;
                            case "f":
                                gender = Gender.FEMALE;
                                break;
                            default:
                                throw new BrokenBankFeedFileException();
                        }
                        break;
                    default:
                        throw new BrokenBankFeedFileException();
                }
            }
            if (name == null || gender == null || accountTypeString == null) {
                throw new BrokenBankFeedFileException();
            }
            Client client = new Client(name, gender);
            Account account;
            switch (accountTypeString) {
                case "s":
                    account = new SavingAccount(balance);
                    break;
                case "c":
                    account = new CheckingAccount(balance, overdraft);
                    break;
                default:
                    throw new BrokenBankFeedFileException();
            }
            client.addAccount(account);
            try {
                bank.addClient(client);
            } catch (ClientExistsException e) {
                e.printStackTrace();
                throw new BrokenBankFeedFileException();
            }
        }
    }
}